import React, {useState, useCallback, memo} from 'react';
import {
  StyleSheet,
  View,
  Text,
  Pressable,
  Button,
  FlatList,
} from 'react-native';
import {PanGestureHandler} from 'react-native-gesture-handler';
import Animated, {runOnJS, withTiming} from 'react-native-reanimated';
import {
  useSharedValue,
  useAnimatedStyle,
  useAnimatedGestureHandler,
  withSpring,
} from 'react-native-reanimated';
import {SafeAreaView} from 'react-native-safe-area-context';

const PressableAnimated = Animated.createAnimatedComponent(Pressable);
const FlatListAnimated = Animated.createAnimatedComponent(FlatList);

let RowItem = (props) => {
  const {renderItem, item, keyToIndex, itemKey, index} = props;

  const drag = () => {
    const {drag: dragFunc} = props;
    const hoverComponent = renderItem({
      isActive: true,
      item,
      index: index,
      drag: () =>
        console.warn('## attempt to call drag() on hovering component'),
    });
    dragFunc(hoverComponent, itemKey);
  };

  return renderItem({
    isActive: false,
    item,
    index: index,
    drag,
  });
};

RowItem = memo(RowItem);

export default function App(props) {
  const [hoverComponent, setHoverComponent] = useState(null);
  const y = useSharedValue(0);

  const gestureHandler = useAnimatedGestureHandler({
    onStart: (_, ctx) => {
      ctx.startY = y.value;
    },
    onActive: (event, ctx) => {
      console.log('active', event.translationY);
      y.value = ctx.startY + event.translationY;
    },
    onEnd: (_) => {
      y.value = withTiming(0, {}, () => {
        runOnJS(reset)();
      });
    },
  });

  function reset() {
    setHoverComponent(null);
  }

  const animatedStyle = useAnimatedStyle(() => {
    console.log(y.value);
    return {
      transform: [
        {
          translateY: y.value,
        },
      ],
    };
  });

  const CellRendererComponent = useCallback(
    (cellProps) => {
      const {item, index, children, onLayout} = cellProps;
      const isActiveCell = index === hoverComponent;
      return (
        <Animated.View pointerEvents={isActiveCell ? 'none' : 'auto'}>
          <Animated.View style={isActiveCell ? {opacity: 0} : undefined}>
            {children}
          </Animated.View>
        </Animated.View>
      );
    },
    [hoverComponent],
  );

  const renderItem = useCallback(
    ({item, index}) => {
      return (
        <RowItem
          extraData={props.extraData}
          itemKey={index}
          renderItem={props.renderItem}
          item={item}
          drag={drag}
        />
      );
    },
    [drag, props.extraData, props.renderItem],
  );

  const renderHoverComponent = () => {
    const hoverStyle = {backgroundColor: 'red', position: 'absolute', top: 100};
    return (
      <PressableAnimated
        onLongPress={drag}
        style={[styles.block, hoverStyle, animatedStyle]}>
        <Text>here is a block text</Text>
      </PressableAnimated>
    );
  };

  const drag = useCallback(
    (component, key) => {
      if (hoverComponent) {
        console.warn("## Can't set multiple active items");
      } else {
        setHoverComponent(key);
      }
    },
    [hoverComponent],
  );

  return (
    <SafeAreaView style={{flex: 1}}>
      <PanGestureHandler onGestureEvent={gestureHandler}>
        <Animated.View
          style={styles.wrapper}
          onTouchEnd={() => {
            console.log('handleTouchEnd');
            reset();
          }}>
          <FlatListAnimated
            {...props}
            renderItem={renderItem}
            CellRendererComponent={CellRendererComponent}
            scrollEnabled={!hoverComponent}
            keyExtractor={(item, index) => `draggable-item-${index}`}
          />
          {!!hoverComponent && renderHoverComponent()}
        </Animated.View>
      </PanGestureHandler>
    </SafeAreaView>
  );
}

const styles = StyleSheet.create({
  wrapper: {
    backgroundColor: '#ddd',
    flex: 1,
  },
  block: {
    height: 100,
    width: '100%',
    backgroundColor: 'green',
    justifyContent: 'center',
    alignItems: 'center',
  },
});
